package handler

import (
	"context"
	"crypto/md5"
	"github.com/golang/protobuf/ptypes/empty"
	"go.uber.org/zap"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"google.golang.org/protobuf/types/known/emptypb"
	"gorm.io/gorm"
	"shop/user-srv/global"
	"time"

	"shop/user-srv/model"
	"shop/user-srv/proto"
)

type UserServer struct {
}

func ModelToResponse(user model.User) proto.UserInfoResponse {
	userInfoResp := proto.UserInfoResponse{
		Id:       user.ID,
		Password: user.Password,
		NickName: user.NickName,
		Mobile:   user.Mobile,
		Gender:   user.Gender,
		Role:     user.Role,
	}
	if user.Birthday != nil {
		userInfoResp.BirthDay = uint64(user.Birthday.Unix())
	}
	return userInfoResp
}

func Paginate(page, pageSize int) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {

		if page <= 0 {
			page = 1
		}
		switch {
		case pageSize > 100:
			pageSize = 100
		case pageSize <= 0:
			pageSize = 10
		}

		offset := (page - 1) * pageSize
		return db.Offset(offset).Limit(pageSize)
	}
}

func (s *UserServer) GetUserList(ctx context.Context, req *proto.PageInfo) (*proto.UserListResponse, error) {
	var users []model.User

	result := global.Db.Find(&users)
	zap.S().Info("用户列表")
	if result.Error != nil {
		return nil, result.Error
	}
	resp := &proto.UserListResponse{}
	resp.Total = int32(result.RowsAffected)
	global.Db.Scopes(Paginate(int(req.Pn), int(req.Psize))).Find(&users)
	for _, user := range users {
		userInfoResponse := ModelToResponse(user)
		resp.Data = append(resp.Data, &userInfoResponse)
	}
	return resp, nil
}

func (s *UserServer) GetUserByMobile(ctx context.Context, req *proto.MobileRequest) (*proto.UserInfoResponse, error) {
	var user model.User
	result := global.Db.Where(&model.User{Mobile: req.Mobile}).First(&user)
	if result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "用户不存在")
	}
	userInfoResponse := ModelToResponse(user)
	return &userInfoResponse, nil

}

func (s *UserServer) GetUserById(ctx context.Context, req *proto.IdRequest) (*proto.UserInfoResponse, error) {
	var user model.User
	result := global.Db.First(&user, req.Id)
	if result.RowsAffected == 0 {
		return nil, status.Errorf(codes.NotFound, "用户不存在")
	}
	if result.Error != nil {
		return nil, result.Error
	}
	userInfoResponse := ModelToResponse(user)
	return &userInfoResponse, nil
}
func (s *UserServer) CreateUser(ctx context.Context, req *proto.CreateUserInfoRequest) (*proto.UserInfoResponse, error) {
	var user model.User

	result := global.Db.Where(&model.User{Mobile: req.Mobile}).First(&user)
	if result.RowsAffected == 1 {
		return nil, status.Errorf(codes.AlreadyExists, "用户已存在")
	}
	user.Mobile = req.Mobile
	user.NickName = req.NickName
	var options = Options{
		SaltLen:      10,
		Iterations:   100,
		KeyLen:       10,
		HashFunction: md5.New,
		OriginalPwd:  req.Password,
	}
	_, password := PasswordEncode(options)
	user.Password = password

	result = global.Db.Create(&user)
	if result.Error != nil {
		return nil, status.Errorf(codes.Internal, "内部错误")
	}
	userInfoResp := ModelToResponse(user)
	return &userInfoResp, nil
}

func (s *UserServer) UpdateUser(ctx context.Context, req *proto.UpdateUserInfoRequest) (*emptypb.Empty, error) {
	var user model.User
	result := global.Db.Where(&model.User{Mobile: req.Mobile}).First(&user)
	if result.RowsAffected == 0 {
		return nil, status.Errorf(codes.ResourceExhausted, "用户不存在")
	}
	birthDay := time.Unix(int64(req.BirthDay), 0)
	user.NickName = req.Nickname
	user.Birthday = &birthDay
	user.Gender = req.Gender

	result = global.Db.Save(user)
	if result.Error != nil {
		return nil, status.Errorf(codes.Internal, result.Error.Error())
	}
	return &empty.Empty{}, nil
}

func (s *UserServer) CheckPassword(ctx context.Context, req *proto.CheckPasswordRequest) (*proto.CheckResponse, error) {
	//VerifyPassword()
	var c proto.CheckResponse
	c.Success = true
	return &c, nil
}
